package org.weasel.controllers;

import java.util.ArrayList;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.weasel.business.Company;
import org.weasel.business.Developer;
import org.weasel.business.Iteration;
import org.weasel.business.Project;
import org.weasel.business.Release;
import org.weasel.business.UserStory;
import org.weasel.models.ChangeListener;
import org.weasel.tree.TreeObjectProject;
import org.weasel.views.BurndownChartComposite;
import org.weasel.views.DeveloperComposite;
import org.weasel.views.ProjectDetail;
import org.weasel.views.TimeChartComposite;

public class ProjectViewController implements ChangeListener {
	private static ProjectViewController instance = null;
	private ApplicationController appController;
	private DeveloperCompositeController devCompController;
	private BurndownChartController burndownChartController;
	private TimeChartController timeChartController;
	private TreeObjectProject to_project;
	private Company comp; //is needed because of the moving of developers
	private ProjectDetail projectView;
	
	public static ProjectViewController instance() {
		if(instance == null)
			instance = new ProjectViewController();
		return instance;
	}
	
	private ProjectViewController() {
	}
	
	public void setApplicationController(ApplicationController appController){
		this.appController = appController;
		this.appController.registerListener(this);
	}

	public void setTo_project(TreeObjectProject to_project) {
		this.to_project = to_project;
	}
	
	public void setComp(Company comp) {
		this.comp = comp;
	}
	
	public Project getProject() {
		return to_project.getProject();
	}

	public Company getComp(){
		return comp;
	}

	public void showProjectView() {
		//attach the appropriate DeveloperComposite controller
		if(devCompController==null){
			devCompController = new DeveloperCompositeController();
			devCompController.setProjectViewController(this);
			devCompController.initializeLists(comp.getDevelopers(), to_project.getProject().getDevelopers());
		}else{
			devCompController.initializeLists(comp.getDevelopers(), to_project.getProject().getDevelopers());
			devCompController.refreshComposite();
		}
		
		if(burndownChartController==null){
			burndownChartController = new BurndownChartController();
			burndownChartController.setProjectViewController(this);
		}
		if(timeChartController==null){
			timeChartController = new TimeChartController();
			timeChartController.setProjectViewController(this);
		}
		try {
//			PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(ProjectDetail.ID, to_project.getProject().getId(),IWorkbenchPage.VIEW_ACTIVATE);
			PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(ProjectDetail.ID);
		} catch (Exception e) {
			e.printStackTrace();
		}
		IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
//		IViewReference ref =  page.findViewReference(ProjectDetail.ID,to_project.getProject().getId());
//		IViewPart viewPart = ref.getView(false);
//		ProjectDetail projectView = (ProjectDetail) viewPart;
		projectView = (ProjectDetail) page.findView(ProjectDetail.ID);
		projectView.showProjectInformation(to_project.getProject());
		burndownChartController.refreshComposite();
		timeChartController.refreshComposite();
	}
	
	/**
	 * Needed to update the view if something changes in the model,
	 * i.e. developers are deleted
	 *
	 */
	public void updateProjectViews(){
		//handle multiple views here! Traverse a collection where views are kept and
		//call the method below
		if(projectView!=null){
			devCompController.refreshComposite();
			projectView.showProjectInformation(to_project.getProject());
		}
	}

	public void setProjectName(String text) {
		to_project.getProject().setName(text);
		to_project.setName(text);
		appController.refreshTreeViewer();
		appController.changesOccured();
	}

	public void setNotes(String text) {
		to_project.getProject().setNotes(text);	
		appController.changesOccured();
	}

	public void setProjectStartDate(String text) {
		to_project.getProject().setStartDate(text);
		appController.changesOccured();
	}
	
	public DeveloperComposite createDeveloperComposite(Composite parent, int style) {
		return devCompController.loadDeveloperComposite(parent, style);
	}

	public void addDeveloper(Developer developer) {
		to_project.getProject().addDeveloper(developer);
//		appController.updateViews();
		appController.changesOccured();
	}

	public void removeDeveloper(Developer developer) {
		if(MessageDialog.openConfirm(projectView.getSite().getShell(), "Confirm", "Do You really want to remove developer \"" + developer.getName() + "\" from project \"" + to_project.getProject().getName() + "\"?\n" +
				"This will have the effect that the developer will be removed also from all userstories he is involved in!")){
			to_project.getProject().removeDeveloper(developer.getId());
			//remove also from all user-stories if it is involved in some
			ArrayList<UserStory> userStories = to_project.getProject().getUnscheduled().getUserStories();
			ArrayList<Release> releases = to_project.getProject().getReleases();
			for (Release release : releases) {
				userStories.addAll(release.getUnscheduled().getUserStories());
				ArrayList<Iteration> iterations = release.getIterations();
				for (Iteration iteration : iterations) {
					userStories.addAll(iteration.getUserStories());
				}
			}
			
			//now scan for the participation of the selected developer and remove it
			for (UserStory userstory : userStories) {
				if(userstory.getDeveloper(developer.getId())!=null)
					userstory.removeDeveloper(developer.getId());
			}
//			appController.updateViews();
			appController.changesOccured();
		}
	}
	
	public void calculateDates(){
		appController.calculateDates();
		appController.updateViews();
	}

	/**
	 * This is called, when the Composite of the View
	 * is disposed...we need to do some stuff to be
	 * able to startup the view the next time successfully
	 *
	 */
	public void doViewClosedActions() {
		this.devCompController = null;
		this.appController.unregisterListener(this);
	}

	public BurndownChartComposite createBurndownchartComposite(Composite top, int none) {
		return burndownChartController.loadBurndownComposite(top, none);
	}
	
	public TimeChartComposite createTimeChartComposite(Composite top, int none) {
		return timeChartController.loadTimeChartComposite(top, none);
	}

	public void changeHappened() {
		if(burndownChartController!=null)
			burndownChartController.refreshComposite();
		if(timeChartController!=null)
			timeChartController.refreshComposite();
	}

}
